package projet;

/**
 * Classe principale
 * @author Aida Tapsoba
 * @author Nicolas Proust
 * @author Celine Barillere
 */

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import projet.simulateur.Generateur;
import projet.simulateur.Ordonnanceur;
import projet.tache.Tache;
import projet.tache.TacheAperiodique;
import projet.tache.TachePeriodique;

public class Main {

	/** le fichier dans lequel sont definies les taches a generer */
	static String FICHIER = "src//FichierTaches.txt";
	/** le fichier dans lequel sont ecrites les taches generees */
	static String FICHIER_GEN = "src//TachesGenerees.txt";
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Generateur generation = new Generateur();
		Ordonnanceur ordonnancement = new Ordonnanceur();
		
		ArrayList<Tache> listeTachePeriodique = new ArrayList<Tache>();
		ArrayList<Tache> listeTacheAperiodique = new ArrayList<Tache>();
		HashMap<String,ArrayList<Tache>> mapTache = new HashMap<String,ArrayList<Tache>>();
		Tache tache = null;
		ArrayList<Tache> diagramme = new ArrayList<Tache>();
		
		String choix = null;
		int nombre = 0;
		int hyperPeriode = 0;
		int ppcmMax = 0;
		double Up = 0.0;
		double Us = 0.0;
		boolean quit = false;
		boolean quitchoix = false;
		
		BufferedReader clavier = new BufferedReader(new InputStreamReader(System.in));
		
		while (!quit) {
			try {
				System.out.println("1- Generation controlee");
				System.out.println("2- Generation aleatoire");
				System.out.println("3- Quitter le programme");
				
				//Lecture du choix de l'utilisateur
				choix = clavier.readLine();
				
				//**************************************************//
				//************** Generation controlee *************//
				//**************************************************//
				if(choix.equals("1")) {	
					System.out.println("Creation des taches periodiques");
					
					//**************************************************//
					//********* Creation des taches periodiques ********//
					//**************************************************//	
						
					System.out.println("1 - Entrer les parametres des taches a creer");
					System.out.println("2 - Utiliser un fichier");
						
					choix = clavier.readLine();
						
					//**************************************************//
					//*************** Generation manuelle **************//
					//**************************************************//
					if (choix.equals("1")) {	
						listeTachePeriodique = generationManuelle("1", clavier); // "1" = taches periodiques
						System.out.println("Voulez vous generer des taches aperiodiques ? oui/non");
						choix = clavier.readLine();
						if (choix.equals("oui")) {
							listeTacheAperiodique = generationManuelle("2", clavier); // "2" = taches aperiodiques
						}	
					} 
					//**************************************************//
					//************ Utilisation d'un fichier ************//
					//**************************************************//
					else if (choix.equals("2")) {
							mapTache = generation.getListeToutesTaches();
							listeTachePeriodique = mapTache.get("tachePeriodique");
							listeTacheAperiodique = mapTache.get("tacheAperiodique");
					}
				}
				//**************************************************//
				//************** Generation aleatoire **************//
				//**************************************************//
				else if(choix.equals("2")) {
					//Choix du nombre de taches
					System.out.println("Combien de taches periodiques faut-il generer ?");
					choix = clavier.readLine();
					nombre = Integer.parseInt(choix);
					//Choix du nombre max pour le ppcm
					System.out.println("Saisir la valeur max du PPCM.");
					choix = clavier.readLine();
					ppcmMax = Integer.parseInt(choix);
					//Choix du facteur
					System.out.println("Quel est le facteur d'utilisation pour ces taches ?");
					choix = clavier.readLine();
					Up = Double.parseDouble(choix);
					mapTache = generation.getListeTachesAleatoire(nombre, Up, ppcmMax);
					listeTachePeriodique = mapTache.get("tachePeriodique");
					listeTacheAperiodique = mapTache.get("tacheAperiodique");
				} 
				else {
					quit = true;
				}
				
				if (!quit) {
					// Verification de la liste des taches generees pour affichage
					if (!listeTachePeriodique.isEmpty() && listeTachePeriodique != null) {
						//Affichage des taches periodiques generees
						Iterator<Tache> it = listeTachePeriodique.iterator();
						while (it.hasNext()) {
							tache = (Tache) it.next();
							System.out.println(tache);
						}
						//Ecriture des taches generees dans un fichier
						File file = new File(FICHIER_GEN);
						file.delete();
						ecrireFichierTache(listeTachePeriodique);
					
						if (!listeTacheAperiodique.isEmpty() && listeTacheAperiodique != null) {
							//Affichage des taches aperiodiques generees
							Iterator<Tache> itAp = listeTacheAperiodique.iterator();
							while (itAp.hasNext()) {
								tache = (TacheAperiodique) itAp.next();
								System.out.println(tache);
							}
							//Ecriture des taches generees dans un fichier
							ecrireFichierTache(listeTacheAperiodique);
						}
						
						quitchoix = false;
						while (!quitchoix) {
							//Choix du type d'ordonnancement
							System.out.println("");
							System.out.println("Quel ordonnancement?");
							System.out.println("1 - RM");
							System.out.println("2 - EDF");
							if (!listeTacheAperiodique.isEmpty()) {
								System.out.println("3 - RM-BG");
								System.out.println("4 - EDF-BG");
								System.out.println("5 - EDF-TBS");
							}
							System.out.println("6 - Quitter les choix d'ordonnancement");
							
							choix = clavier.readLine();
		
							// Recuperation de l'hyper periode
							hyperPeriode = generation.getHyperPeriode(listeTachePeriodique);
							
							// Algorithme d'ordonnancement RM
							if (choix.equals("1")) {
								diagramme = ordonnancement.ordoRM(listeTachePeriodique, hyperPeriode);
								ordonnancement.createFileKtr(listeTachePeriodique, null, diagramme, hyperPeriode);
							} 
							// Algorithme d'ordonnancement EDF
							else if (choix.equals("2")){
								diagramme = ordonnancement.ordoEDF(listeTachePeriodique, hyperPeriode);
								ordonnancement.createFileKtr(listeTachePeriodique, null, diagramme, hyperPeriode);
							} 
							// Algorithme d'ordonnancement RM-BG
							else if (choix.equals("3")) {
								diagramme = ordonnancement.ordoRM(listeTachePeriodique, hyperPeriode);
								diagramme = ordonnancement.ordoBG(diagramme, listeTacheAperiodique, hyperPeriode);
								ordonnancement.createFileKtr(listeTachePeriodique, listeTacheAperiodique, diagramme, hyperPeriode);
							}
							// Algorithme d'ordonnancement EDF-BG
							else if (choix.equals("4")) {
								diagramme = ordonnancement.ordoEDF(listeTachePeriodique, hyperPeriode);
								diagramme = ordonnancement.ordoBG(diagramme, listeTacheAperiodique, hyperPeriode);
								ordonnancement.createFileKtr(listeTachePeriodique, listeTacheAperiodique, diagramme, hyperPeriode);
							}
							// Algorithme d'ordonnancement EDF-TBS
							else if (choix.equals("5")) {
								System.out.println("Quel est le facteur Us ?");
								choix = clavier.readLine();
								Us = Double.parseDouble(choix);
								diagramme = ordonnancement.ordoTBS(listeTachePeriodique, listeTacheAperiodique, hyperPeriode, Us);
								ordonnancement.createFileKtr(listeTachePeriodique, listeTacheAperiodique, diagramme, hyperPeriode);
							}
							else {
								quitchoix = true;
							}
						}
		
					} else {
						System.out.println("Aucune tache n'a ete generee.");
					}
				}

			//Si l'utilisateur a saisi autre chose qu'un nombre
			} catch (NumberFormatException e) {
				System.out.println("Vous devez entrer un nombre.");
			} catch (IOException e1) {
				System.out.println(e1.getMessage());
			}
		}	
	}

	
	/**
	 * Permet de generer des taches de facon manuelle
	 * @param choix
	 * @param clavier
	 * @return une liste de taches
	 * @throws NumberFormatException
	 * @throws IOException
	 */
	private static ArrayList<Tache> generationManuelle(String choix, BufferedReader clavier) throws NumberFormatException, IOException {
		ArrayList<Tache> listeTache = new ArrayList<Tache>();
		Tache tache = null;
		String parametres = null;
		String[] parametre;
		int nombre = 0;
		
		System.out.println("Combien de taches faut-il generer?");
		//Recuperation du nombre de taches a generer
		nombre = Integer.parseInt(clavier.readLine());
		
		for (int i = 1; i<=nombre; i++) {
			//Periodique
			if (choix.equals("1")) {
				System.out.println("Entrez les parametres Ci, Pi et Di pour la " + i + "e tache.(separez chaque parametre par des espaces)");
				parametres = clavier.readLine();
				parametre = parametres.split(" ");
				if (parametre.length != 3) {
					System.out.println("Erreur lors de la saisie des parametres");
					i--;		
				} else {
					tache = new TachePeriodique("tp"+i, Integer.parseInt(parametre[0]), Integer.parseInt(parametre[1]), Integer.parseInt(parametre[2]));
					listeTache.add(tache);
				}
			//Aperiodique
			} else if (choix.equals("2")) {
				System.out.println("Entrez les parametres Ri,Ci pour la " + i + "e tache.(separez chaque parametre par des espaces)");
				parametres = clavier.readLine();
				parametre = parametres.split(" ");
				if (parametre.length != 2) {
					System.out.println("Erreur lors de la saisie des parametres");
					i--;		
				} else {
					tache = new TacheAperiodique("ta"+i, Integer.parseInt(parametre[0]), Integer.parseInt(parametre[1]));
					listeTache.add(tache);
				}
			}
		}
		return listeTache;
	}
	
	
	/**
	 * Permet d'ecrire une liste de taches dans un fichier 
	 * @param listeTache une liste d'objet Tache
	 */
	private static void ecrireFichierTache(ArrayList<Tache> listeTache) {
		String fichier = FICHIER_GEN;
		Tache tache = null;
		
		try {
			FileWriter fw = new FileWriter(fichier, true);
			BufferedWriter output = new BufferedWriter(fw);
			Iterator<Tache> it = listeTache.iterator();
			while (it.hasNext()) {
				tache = it.next();
				output.write(tache.toString());
				output.newLine();
			}
			output.flush(); 
			output.close();
			System.out.println("Fichier des taches cree");
		} catch(IOException ioe) {
			System.out.print("Erreur : ");
			ioe.printStackTrace();
		}
	}
}
